package top.csmcool.musicapi.client;

/*
 * @description
 * @date 2025/1/29
 * @author shijin
 * @version 1.0
 */

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import top.csmcool.musicapi.config.SystemProperties;
import top.csmcool.musicapi.domain.Users;
import top.csmcool.musicapi.enums.PlatformEnum;
import top.csmcool.musicapi.model.api.navidrome.*;
import top.csmcool.musicapi.util.CacheWithExpiry;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@RequiredArgsConstructor
public class NavidromeClient extends CommonClient{

    private final SystemProperties systemProperties;
    private CacheWithExpiry<String, NavidromeLoginResult> cache = new CacheWithExpiry<>(60 * 60 * 1000); // 默认5秒过期时间

    private static final String PLAYLIST_TACKS_URL = "/api/playlist/%s/tracks";

    private static final String PLAYLIST_URL = "/api/playlist";

    private static final String SEARCH_SONG_URL = "/api/song";

    private static final String SONG_URL = "/api/song/%s";


    public NavidromeLoginResult getTokenInfo(String url,String username, String password) {
        if(cache.get(username) != null) {
            return cache.get(username);
        }

        String loginUrl = url + "/auth/login";
        HashMap<String,String> param = new HashMap<>();
        param.put("username", username);
        param.put("password", password);
        String result = HttpRequest.post(loginUrl)
                .body(JSONUtil.toJsonStr(param))
                .timeout(5000)//超时，毫秒
                .execute().body();

        if(result.contains("error")) {
            throw new RuntimeException("远程登录失败");
        }

        NavidromeLoginResult navidromeLoginResult =
                JSONUtil.toBean(result, NavidromeLoginResult.class);


        cache.put(username, navidromeLoginResult);
        return navidromeLoginResult;
    }

    public List<MusicTrack> getMusicTracks(NavidromeLoginResult tokenInfo,
                                          String url,
                                          String pid,
                                          int start,
                                          int end) {
        String getPlayListDetailsUrl = url + String.format(PLAYLIST_TACKS_URL +
                "?_end=%s&_start=%s",
                pid,
                end,
                start);

        String queryUserResult = HttpRequest.get(getPlayListDetailsUrl)
                .header("x-nd-authorization", "Bearer " + tokenInfo.getToken())
                .header("x-nd-client-unique-id", tokenInfo.getId())
                .timeout(5000)//超时，毫秒
                .execute().body();

        JSONArray objects = JSONUtil.parseArray(queryUserResult);
        return JSONUtil.toList(objects, MusicTrack.class);
    }

    public List<SongCollection> getPlayLists(NavidromeLoginResult tokenInfo,
                                             String url,
                                             int start,
                                             int end) {
        String getPlayListUrl = url + String.format(PLAYLIST_URL +
                        "?_end=%s&_start=%s&_order=ASC&_sort=id" +
                        "&owner_id=%s",
                end,
                start,
                tokenInfo.getId());

        String queryUserResult = HttpRequest.get(getPlayListUrl)
                .header("x-nd-authorization", "Bearer " + tokenInfo.getToken())
                .header("x-nd-client-unique-id", tokenInfo.getId())
                .timeout(5000)//超时，毫秒
                .execute().body();

        JSONArray objects = JSONUtil.parseArray(queryUserResult);
        return JSONUtil.toList(objects, SongCollection.class);
    }

    public List<SongCollection> getPublicPlayLists(NavidromeLoginResult tokenInfo,
                                             String url,
                                             int start,
                                             int end) {
        String getPlayListUrl = url + String.format(PLAYLIST_URL +
                        "?_end=%s&_start=%s&_order=DESC&_sort=updatedAt" +
                        "&public=1",
                end,
                start);

        String queryUserResult = HttpRequest.get(getPlayListUrl)
                .header("x-nd-authorization", "Bearer " + tokenInfo.getToken())
                .header("x-nd-client-unique-id", tokenInfo.getId())
                .timeout(5000)//超时，毫秒
                .execute().body();

        JSONArray objects = JSONUtil.parseArray(queryUserResult);
        return JSONUtil.toList(objects, SongCollection.class);
    }

    public SongInfo getSongInfo(NavidromeLoginResult tokenInfo, String url, String mid) {
        String musicInfoUrl = url + String.format(SONG_URL, mid);
        String queryUserResult = HttpRequest.get(musicInfoUrl)
                .header("x-nd-authorization", "Bearer " + tokenInfo.getToken())
                .header("x-nd-client-unique-id", tokenInfo.getId())
                .timeout(5000)//超时，毫秒
                .execute().body();

        return JSONUtil.toBean(queryUserResult, SongInfo.class);
    }

    public List<MusicTrack> search(NavidromeLoginResult tokenInfo,
                                           String url,
                                           String name,
                                           int start,
                                           int end) {
        // https://musicapi.csmcool.top/api/song
        // ?_end=15
        // &_order=ASC
        // &_sort=title
        // &_start=0
        // &title=%E6%94%B9%E5%8F%98%E8%87%AA%E5%B7%B1
        String searchSongUrl = url + String.format(SEARCH_SONG_URL +
                        "?_end=%s&_start=%s&_order=ASC&_sort=title&title=%s",
                end,
                start,
                name);

        String queryUserResult = HttpRequest.get(searchSongUrl)
                .header("x-nd-authorization", "Bearer " + tokenInfo.getToken())
                .header("x-nd-client-unique-id", tokenInfo.getId())
                .timeout(10000)//超时，毫秒
                .execute().body();

        JSONArray objects = JSONUtil.parseArray(queryUserResult);
        return JSONUtil.toList(objects, MusicTrack.class);
    }

    public NavidromeLoginResult getTokenInfo() {
        return getTokenInfo(systemProperties.getRegisterUrl(),
                systemProperties.getNavidromeUsername(),
                systemProperties.getNavidromePassword());
    }

    public NavidromeUserInfo getUserInfos(String username, String token, String id) {
        // https://musicapi.csmcool.top/api/user
        //https://musicapi.csmcool.top/api/user?_end=15&_order=ASC&_sort=userName&_start=0&name=userMusicPlatform.getUsername()
        String queryUser = systemProperties.getRegisterUrl()
                + "/api/user?_end=15&_order=ASC&_sort=userName&_start=0&name="
                + username;

        String queryUserResult = HttpRequest.get(queryUser)
                .header("x-nd-authorization", "Bearer " + token)
                .header("x-nd-client-unique-id", (String) id)
                .timeout(5000)//超时，毫秒
                .execute().body();

        JSONArray objects = JSONUtil.parseArray(queryUserResult);
        List<NavidromeUserInfo> userList = JSONUtil.toList(objects, NavidromeUserInfo.class);
        if(userList.isEmpty()) {
            return null;
        }

        return userList.stream().filter(u -> u.getUserName().equals(username)).findFirst().orElse(null);
    }

    public String adUserInfos(Users userMusicPlatform, String token, String id) {
        String addUserUrl = systemProperties.getRegisterUrl() + "/api/user";
        Map<String, Object> addUserInfo = new HashMap<>();
        addUserInfo.put("isAdmin", false);
        addUserInfo.put("userName", userMusicPlatform.getUsername());
        addUserInfo.put("password", userMusicPlatform.getPassword());
        addUserInfo.put("name", userMusicPlatform.getDisplayName());
        addUserInfo.put("email", userMusicPlatform.getEmail());

        String addUserResult = HttpRequest.post(addUserUrl)
                .body(JSONUtil.toJsonStr(addUserInfo))
                .header("x-nd-authorization", "Bearer " + token)
                .header("x-nd-client-unique-id", (String) id)
                .timeout(5000)//超时，毫秒
                .execute().body();
        if(addUserResult.contains("error")) {
            return null;
        }

        JSONObject parseObj =  JSONUtil.parseObj(addUserResult);

        return (String) parseObj.get("id");
    }

    public JSONObject requestResource(NavidromeLoginResult tokenInfo, String platformUrl, JSONObject jsonObject) {
        String requestMethod = jsonObject.getStr("requestMethod");
        String requestUrl = platformUrl + jsonObject.getStr("url");
        // 需要拼接参数
        if(jsonObject.getStr("queryArg") != null) {
            requestUrl = requestUrl + generateGetRequestUrl(jsonObject.getJSONObject("queryArg"));
        }
        if(!StringUtils.hasText(requestMethod) || requestMethod.equals("GET")) {
            String requestResult = HttpRequest.get(requestUrl + platformUrl)
                    .header("x-nd-authorization", "Bearer " + tokenInfo.getToken())
                    .header("x-nd-client-unique-id", tokenInfo.getId())
                    .timeout(5000)//超时，毫秒
                    .execute().body();
            return JSONUtil.parseObj(requestResult);
        }

        if(requestMethod.equals("POST")) {
            String requestResult = HttpRequest.post(requestUrl)
                    .body(JSONUtil.toJsonStr(jsonObject))
                    .header("x-nd-authorization", "Bearer " + tokenInfo.getToken())
                    .header("x-nd-client-unique-id", tokenInfo.getId())
                    .timeout(5000)//超时，毫秒
                    .execute().body();
            return JSONUtil.parseObj(requestResult);
        }

        return null;
    }

    @Override
    public PlatformEnum getPlatform() {
        return PlatformEnum.NAVIDROME;
    }
}
